﻿Imports System.Data.OleDb
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports Microsoft.ML
Imports Microsoft.Office.Interop.Access

Public Class E3_モデルデータ作成F
#Region "画面操作"

    ' クラスレベル変数はK1.vbで宣言
    Private 閉じる要求 As Boolean = False

    ' Windows API for keyboard state
    <DllImport("user32.dll")>
    Private Shared Function GetAsyncKeyState(ByVal vKey As Keys) As Short
    End Function

    Private Sub E3_モデルデータ作成F_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        著作L.Text = 著作
        フォルダー確認()
        My_DATA2読込()   'ベースE数 ベースI数 を読入る
        ' フォームの初期設定のみ
        進行状況L.Text = "..."
    End Sub
    Private Sub E3_モデルデータ作成実行Bt_Click(sender As Object, e As EventArgs) Handles E3_モデルデータ作成実行Bt.Click
        Try
            進行読込()
        Catch ex As Exception
            MsgBox($"処理エラー: {ex.Message}{vbCrLf}{ex.StackTrace}", MsgBoxStyle.Critical)
            進行状況L.Text = "エラーが発生しました。"
        End Try
    End Sub
    Private Sub E3_閉じるBt_Click(sender As Object, e As EventArgs) Handles E3_閉じるBt.Click
        'Dim result = MsgBox("フォームを閉じますか？",
        '                    MsgBoxStyle.Question Or MsgBoxStyle.YesNo, "閉じる確認")
        'If result = DialogResult.Yes Then
        閉じる要求 = True
        E2_モデルデータ設定F.Close()
        Me.Close()
        'End If
    End Sub
    Private Sub データモデルDgv非表示Rb_CheckedChanged(sender As Object, e As EventArgs) Handles データモデルDgv非表示Rb.CheckedChanged, データモデルDgv表示Rb.CheckedChanged
        ' ラジオボタンの状態に応じてデータモデルDgvの表示/非表示を切り替え
        Try
            If データモデルDgv表示Rb.Checked = True Then
                T600_データモデル表示()
            Else
                ' 非表示
                データモデルDgv.DataSource = Nothing
                データモデルDgv.Visible = False
            End If
        Catch ex As Exception
            ' エラーが発生しても処理を継続（スルー）
        End Try
    End Sub
#End Region

#Region "E3_モデルデータ作成実行Btの処理"

#End Region

    Private Sub 進行読込()
        'MySQL = "UPDATE T160_全出荷E集計 SET T160_全出荷E集計.判定 = ""Yes"" WHERE (((T160_全出荷E集計.乱数)<=0.7));"

        'T300_進行の読込、作成Chk=済が有ればスキップ
        Dim dbPath As String = Tera計算DataPath & "\EIQ分析AI化\EIQ_AIモデル.accdb"
        Dim connStr As String = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={dbPath};"

        Try
            ' まずT300_進行テーブルのデータを全て取得
            Dim 進行データリスト As New List(Of (進行連番 As Integer, 計算E数 As Integer, 計算I数 As Integer, E採用判定値 As Double, I採用判定値 As Double, 作成Chk As String))

            Using conn As New OleDbConnection(connStr)
                conn.Open()

                ' T300_進行テーブルから作成Chk <> "済"のデータを進行連番順に読み込む
                Dim sql As String = "SELECT * FROM T300_進行 WHERE 作成Chk <> '済' OR 作成Chk IS NULL ORDER BY 進行連番"
                Using cmd As New OleDbCommand(sql, conn)
                    Using reader As OleDbDataReader = cmd.ExecuteReader()
                        While reader.Read()
                            Dim データ = (
                                進行連番:=Convert.ToInt32(reader("進行連番")),
                                計算E数:=Convert.ToInt32(reader("計算E数")),
                                計算I数:=Convert.ToInt32(reader("計算I数")),
                                E採用判定値:=Convert.ToDouble(reader("E採用判定値")),
                                I採用判定値:=Convert.ToDouble(reader("I採用判定値")),
                                作成Chk:=If(IsDBNull(reader("作成Chk")), "", reader("作成Chk").ToString())
                            )
                            進行データリスト.Add(データ)
                        End While
                    End Using
                End Using
            End Using

            ' データが取得できたか確認
            If 進行データリスト.Count = 0 Then
                進行状況L.Text = "処理対象のレコードがありません。"
                進行状況L.Refresh()
                MsgBox("処理対象のレコードがありません。" & vbCrLf &
                      "全てのレコードが既に処理済みです。", MsgBoxStyle.Information, "処理対象なし")
                Exit Sub
            End If

            ' 各レコードを処理（SQLでフィルタ済みのため全て処理対象）
            Dim 処理件数 As Integer = 0
            Dim 全件数 As Integer = 進行データリスト.Count
            Dim 中断フラグ As Boolean = False

            For Each データ In 進行データリスト
                ' 閉じるボタンによる中断チェック
                If 閉じる要求 Then
                    中断フラグ = True
                    進行状況L.Text = $"閉じるボタンにより中断されました。({処理件数}/{全件数} 件完了)"
                    進行状況L.Refresh()
                    Exit For
                End If

                進行連番 = データ.進行連番
                計算E数 = データ.計算E数
                計算I数 = データ.計算I数
                E採用判定値 = データ.E採用判定値
                I採用判定値 = データ.I採用判定値

                Try
                    ' 処理開始メッセージ
                    進行状況L.Text = $"進行連番 {進行連番} の処理を開始します。 - Escキーで中断可能"
                    進行状況L.Refresh()
                    System.Windows.Forms.Application.DoEvents()

                    ' Escapeキーのチェック
                    If My.Computer.Keyboard.CtrlKeyDown = False AndAlso My.Computer.Keyboard.AltKeyDown = False AndAlso My.Computer.Keyboard.ShiftKeyDown = False Then
                        If GetAsyncKeyState(Keys.Escape) <> 0 Then
                            Dim result As DialogResult = MsgBox($"処理を中断しますか？{vbCrLf}{vbCrLf}現在の進行状況: {処理件数}/{全件数} 件完了{vbCrLf}{vbCrLf}「はい」: 処理を中断して終了します。{vbCrLf}「いいえ」: 処理を続行します。", MsgBoxStyle.Question Or MsgBoxStyle.YesNo, "処理の中断確認")
                            If result = DialogResult.Yes Then
                                中断フラグ = True
                                進行状況L.Text = $"処理が中断されました。({処理件数}/{全件数} 件完了)"
                                進行状況L.Refresh()
                                MsgBox($"処理を中断しました。{vbCrLf}{vbCrLf}完了件数: {処理件数}/{全件数}", MsgBoxStyle.Information, "処理中断")
                                Exit For
                            End If
                        End If
                    End If
                    Clipboard.SetText(CStr(ベースE数)) ' 変数の値をクリップボードにコピー

                    発送先採用判定("T160_全出荷E集計", 計算条件, 計算E数, E採用判定値)
                    アイテム採用判定("T160_全出荷I集計", 計算条件, 計算I数, I採用判定値)
                    T500_計算対象作成() '
                    T500_計算対象E削除




                    'T350_作成(ベースE数, 計算E数, ベースI数, 計算I数)

                    'T500_計算対象集計と変数読込(進行連番)
                    'T600_データモデル更新0_89(進行連番)
                    'T600_データモデル更新90_164(進行連番)

                    'T600_データモデル作成()   ' T500_計算対象からデータモデル作成


                    進行状況L.Text = $"進行連番 {進行連番}: T500_計算対象を作成中... ({処理件数 + 1}/{全件数})"
                    進行状況L.Refresh()
                    System.Windows.Forms.Application.DoEvents()




                    ' 処理完了後、作成Chkを"済"に更新
                    Using conn As New OleDbConnection(connStr)
                        conn.Open()
                        Dim sqlUpdate As String = "UPDATE T300_進行 Set 作成Chk = ? WHERE 進行連番 = ?"
                        Using cmdUpdate As New OleDbCommand(sqlUpdate, conn)
                            cmdUpdate.Parameters.Add("@作成Chk", OleDbType.VarChar, 10).Value = "済"
                            cmdUpdate.Parameters.AddWithValue("@進行連番", 進行連番)
                            cmdUpdate.ExecuteNonQuery()
                        End Using
                    End Using

                    処理件数 += 1
                    進行状況L.Text = $"進行連番 {進行連番} の処理が完了しました。({処理件数}/{全件数})"
                    進行状況L.Refresh()
                    System.Windows.Forms.Application.DoEvents()

                    ' Accessが肥大化するため、一定件数ごとに最適化(Compact)を実行
                    Try
                        If 処理件数 > 0 AndAlso (処理件数 Mod 50) = 0 Then
                            進行状況L.Text = $"進行連番 {進行連番}: データベース最適化(Compact)を開始します... ({処理件数}/{全件数})"
                            進行状況L.Refresh()
                            System.Windows.Forms.Application.DoEvents()

                            ' GCで接続解放を促してからCompactを実行
                            GC.Collect()
                            GC.WaitForPendingFinalizers()

                            'CompactAccess(dbPath)

                            進行状況L.Text = $"進行連番 {進行連番}: データベース最適化(Compact)が完了しました。 ({処理件数}/{全件数})"
                            進行状況L.Refresh()
                            System.Windows.Forms.Application.DoEvents()
                        End If
                    Catch ex As Exception
                        ' 最適化に失敗しても処理は継続（ログ表示はせずスルー）
                    End Try

                Catch ex As Exception
                    MsgBox($"進行連番 {進行連番} の処理でエラー: {ex.Message}{vbCrLf}{ex.StackTrace}", MsgBoxStyle.Critical)
                    Exit Sub
                End Try
            Next

            If 中断フラグ Then
                ' 中断された場合は何もしない（既にメッセージ表示済み）
            ElseIf 処理件数 > 0 Then
                進行状況L.Text = $"モデルデータ作成が完了しました。処理件数: {処理件数}/{全件数}"
                進行状況L.Refresh()
                MsgBox($"モデルデータ作成が完了しました。{vbCrLf}処理件数: {処理件数}/{全件数}", MsgBoxStyle.Information)
                'If 処理件数 = 全件数 Then
                '    データモデル_csv作成()
                'End If

            Else
                進行状況L.Text = "処理対象のレコードがありませんでした。"
                進行状況L.Refresh()
            End If

            MsgBox($"モデルデータ作成が完了しました。{vbCrLf}処理件数: {処理件数}/{全件数}", MsgBoxStyle.Information)


        Catch ex As Exception
            MsgBox($"進行読込エラー: {ex.Message}{vbCrLf}{ex.StackTrace}", MsgBoxStyle.Critical)
        End Try


        If 進行連番 = 1 Then
            Close()
        End If

    End Sub

#Region " T500_計算対象作成"
    Private Sub T500_計算対象作成()
        ' 1. T200 をコピーして T500_計算対象 を作成、モデル連番を設定追加
        Try
            ' DBパスは K1 モジュールの MyDB を利用
            If String.IsNullOrWhiteSpace(MyDB) Then
                ' MyDB が未設定ならばフォルダ確認を促す
                フォルダー確認()
            End If

            ' T200 が存在するか確認
            If Not Search_Table("T200") Then
                MsgBox("T200 テーブルが見つかりません。T200 を作成してから再実行してください。", MsgBoxStyle.Exclamation)
                Return
            End If

            ' 既存の T500_計算対象 を削除（存在すれば）
            Try
                DEL_table("T500_計算対象*")
            Catch ex As Exception
                ' 削除失敗はログにして続行
            End Try

            ' T200 の構造とデータをコピーして T500_計算対象 を作成
            ' SELECT INTO を使う（T500_計算対象 が存在しない前提）
            Dim sqlCreate As String = "SELECT T200.* INTO [T500_計算対象] FROM [T200];"
            SQL実行(sqlCreate)

            ' モデル連番列を追加（存在していなければ）
            Try
                Dim addColSql As String = "ALTER TABLE [T500_計算対象] ADD COLUMN [モデル連番] INTEGER"
                SQL実行(addColSql)
            Catch ex As Exception
                ' 既に列があれば ALTER は失敗するが処理は継続
            End Try

            ' モデル連番に現在の進行連番を設定
            Try
                Dim updSql As String = "UPDATE [T500_計算対象] SET [モデル連番] = " & 進行連番
                SQL実行(updSql)
            Catch ex As Exception
                ' 更新失敗は通知
                MsgBox("T500_計算対象 のモデル連番設定でエラー: " & ex.Message)
            End Try

            ' 状況表示
            進行状況L.Text = "T500_計算対象 の作成が完了しました。"
            進行状況L.Refresh()
            System.Windows.Forms.Application.DoEvents()

        Catch ex As Exception
            MsgBox("T500_計算対象作成エラー: " & ex.Message)
        End Try
    End Sub
    Private Sub T500_計算対象E削除()
        '2. T500_計算対象 から E採用判定値 < E採用判定値のレコードを削除

    End Sub
    Private Sub T500_計算対象I削除()

    End Sub
#End Region

#Region " T600_データモデル作成"

    Private Sub T600_データモデル表示()
        Dim dbPath As String = Tera計算DataPath & "\EIQ分析AI化\EIQ_AIモデル.accdb"
        Dim connStr As String = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={dbPath};"

        Try
            Using conn As New OleDbConnection(connStr)
                conn.Open()

                ' T600_データモデルテーブルが存在するか確認
                Dim テーブル存在 As Boolean = False
                Dim dt As DataTable = conn.GetSchema("Tables")
                For Each row As DataRow In dt.Rows
                    If row("TABLE_NAME").ToString().ToUpper() = "T600_データモデル".ToUpper() Then
                        テーブル存在 = True
                        Exit For
                    End If
                Next

                If Not テーブル存在 Then
                    ' テーブルが存在しない場合はスルー
                    データモデルDgv.Visible = False
                    Exit Sub
                End If

                ' データが存在するか確認
                Dim sqlCount As String = "SELECT COUNT(*) FROM T600_データモデル"
                Using cmdCount As New OleDbCommand(sqlCount, conn)
                    Dim count As Integer = Convert.ToInt32(cmdCount.ExecuteScalar())
                    If count = 0 Then
                        ' データが無い場合はスルー
                        データモデルDgv.Visible = False
                        Exit Sub
                    End If
                End Using

                ' データを取得して表示
                Dim sql As String = "SELECT * FROM T600_データモデル ORDER BY モデル連番"
                Dim adapter As New OleDbDataAdapter(sql, conn)
                Dim dtData As New DataTable()
                adapter.Fill(dtData)

                データモデルDgv.DataSource = dtData
                データモデルDgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
                データモデルDgv.Visible = True

                ' データバインド完了後に画面を更新
                データモデルDgv.Refresh()
                System.Windows.Forms.Application.DoEvents()

                ' 更新した進行連番の行を表示
                If データモデルDgv.Rows.Count > 0 AndAlso 進行連番 > 0 Then
                    ' モデル連番列のインデックスを取得
                    Dim モデル連番列Index As Integer = -1
                    For i As Integer = 0 To データモデルDgv.Columns.Count - 1
                        If データモデルDgv.Columns(i).Name.ToUpper() = "モデル連番" Then
                            モデル連番列Index = i
                            Exit For
                        End If
                    Next

                    ' モデル連番に一致する行を検索
                    If モデル連番列Index >= 0 Then
                        For i As Integer = 0 To データモデルDgv.Rows.Count - 1
                            If データモデルDgv.Rows(i).IsNewRow Then Continue For

                            Dim セル値 = データモデルDgv.Rows(i).Cells(モデル連番列Index).Value
                            If セル値 IsNot Nothing AndAlso Not IsDBNull(セル値) Then
                                Dim モデル連番値 As Integer = Convert.ToInt32(セル値)
                                If モデル連番値 = 進行連番 Then
                                    ' 該当行が見つかった
                                    データモデルDgv.ClearSelection()
                                    データモデルDgv.Rows(i).Selected = True

                                    ' 該当行の5行上を表示（スクロール）
                                    Dim スクロール位置 As Integer = Math.Max(0, i - 5)
                                    データモデルDgv.FirstDisplayedScrollingRowIndex = スクロール位置

                                    ' 画面を更新
                                    データモデルDgv.Refresh()
                                    System.Windows.Forms.Application.DoEvents()
                                    Exit For
                                End If
                            End If
                        Next
                    End If
                End If

            End Using
        Catch ex As Exception
            ' エラーが発生してもスルー（データが無い場合も含む）
            データモデルDgv.Visible = False
        End Try
    End Sub
#End Region





End Class

